package com.joysuch.wwyt.mh.service.impl;

import cn.hutool.http.HttpRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.service.BaseImageRepositoryService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.mh.bean.*;
import com.joysuch.wwyt.mh.dto.*;
import com.joysuch.wwyt.mh.entity.CustomizeMonitorPoint;
import com.joysuch.wwyt.mh.entity.CustomizeMonitorPointData;
import com.joysuch.wwyt.mh.entity.CustomizeMonitorType;
import com.joysuch.wwyt.mh.enums.PointConnectStateEnum;
import com.joysuch.wwyt.mh.enums.PointShowStateEnum;
import com.joysuch.wwyt.mh.mapper.CustomizeMonitorPointDataMapper;
import com.joysuch.wwyt.mh.mapper.CustomizeMonitorPointMapper;
import com.joysuch.wwyt.mh.service.CustomizeMonitorPointDataService;
import com.joysuch.wwyt.mh.service.CustomizeMonitorPointService;
import com.joysuch.wwyt.mh.service.CustomizeMonitorTypeService;
import com.joysuch.wwyt.mh.websocket.MonitorPointDataWebSocket;
import com.joysuch.wwyt.mh.websocket.WebsocketDataType;
import com.joysuch.wwyt.util.GsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author jingwk
 * @since 2021-07-05
 */
@Service
@Slf4j
public class CustomizeMonitorPointServiceImpl extends ServiceImpl<CustomizeMonitorPointMapper, CustomizeMonitorPoint> implements CustomizeMonitorPointService {

    @Resource
    private CustomizeMonitorPointMapper customizeMonitoringPointMapper;
    @Autowired
    private CustomizeMonitorPointDataService customizeMonitorPointDataService;
    @Resource
    private CustomizeMonitorPointDataMapper customizeMonitorPointDataMapper;
    @Autowired
    private BaseImageRepositoryService baseImageRepositoryService;
    @Autowired
    private CustomizeMonitorTypeService customizeMonitorTypeService;

    @Override
    public IPage<CustomizeMonitorPointDto> findListPaging(CustomizeMonitorPointSearchBean searchBean) {
        Page<CustomizeMonitorPointDto> page = new Page<>(searchBean.getPage() + 1, searchBean.getSize());
        String companyCode = Context.getCompanyCode();
        Long tenantId = Context.getCurrentTenantId();
        IPage<CustomizeMonitorPointDto> pointPage = customizeMonitoringPointMapper.findListPaging(page, searchBean.getNameOrCode(), searchBean.getCustomizeMonitoringTypeId(), searchBean.getTypeCode(), companyCode, tenantId);
        List<CustomizeMonitorPointDto> records = pointPage.getRecords();
        records.forEach(each -> {
            if (PointShowStateEnum.NOT_DISPLAYED.getValue().equals(each.getShowState())) {
                each.setPointStateName(PointConnectStateEnum.DISCONNECT.getDesc());
            } else {
                LambdaQueryWrapper<CustomizeMonitorPointData> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(CustomizeMonitorPointData::getDeleteFlag, "0");
                wrapper.eq(CustomizeMonitorPointData::getTagCode, each.getPointCode());
                List<CustomizeMonitorPointData> pointList = customizeMonitorPointDataService.list(wrapper);
                if (CollectionUtils.isNotEmpty(pointList)) {
                    each.setPointStateName(PointConnectStateEnum.CONNECTED.getDesc());
                } else {
                    each.setPointStateName(PointConnectStateEnum.DISCONNECT.getDesc());
                }
            }
        });
        return pointPage;
    }

    @Override
    public List<CustomizeMonitorTypeUseCountDto> countPointByType() {
        String companyCode = Context.getCompanyCode();
        Long tenantId = Context.getCurrentTenantId();
        return customizeMonitoringPointMapper.countPointByType(companyCode, tenantId);
    }

    @Override
    public boolean pushMonitorPoint(CustomizeMonitorPointDataBean data) throws ApiBusinessException {
        List<CustomizeMonitorPointInfo> pointInfoList = data.getData();
        List<String> pointCodes = pointInfoList.stream().map(CustomizeMonitorPointInfo::getTagCode).collect(Collectors.toList());
        List<CustomizeMonitorDataDto> dataList = customizeMonitorPointDataMapper.selectPointCode(pointCodes, Context.getCompanyCode(), Context.getCurrentTenantId());
        Map<String, Long> codeMap = dataList.stream().collect(Collectors.toMap(CustomizeMonitorDataDto::getTagCode, CustomizeMonitorDataDto::getTagId, (r, v) -> r));
        String companyCode = Context.getCompanyCode();
        Long tenantId = Context.getCurrentTenantId();
        List<CustomizeMonitorPointData> list = new ArrayList<>();
        Set<String> pointCodeSet = new HashSet<>();
        if (CollectionUtils.isNotEmpty(pointInfoList)) {
            pointInfoList.forEach(each -> {
                if (StringUtils.isNotBlank(each.getTagCode())) {
                    CustomizeMonitorPointData point = new CustomizeMonitorPointData();
                    point.setTagCode(each.getTagCode());
                    point.setTagTime(each.getTagTime());
                    point.setTagValue(each.getTagValue());
                    point.setRemark(each.getRemark());
                    point.setExt1(each.getExt1());
                    point.setExt2(each.getExt2());
                    point.setExt3(each.getExt3());
                    point.setOrgCode(companyCode);
                    point.setTenentId(tenantId);
                    if (MapUtils.isNotEmpty(codeMap) && codeMap.containsKey(each.getTagCode())) {
                        point.setTagId(codeMap.get(each.getTagCode()));
                    }
                    if (!pointCodeSet.contains(each.getTagCode())) {
                        list.add(point);
                    }
                    pointCodeSet.add(each.getTagCode());
                }
            });
        }
        if (CollectionUtils.isNotEmpty(list)) {
            //推送大屏更新数据
            pushMonitorPoint();
            return customizeMonitorPointDataService.saveOrUpdateBatch(list, 500);
        } else {
            throw new ApiBusinessException(Status.NOTHING);
        }
    }

    @Override
    public void pushMonitorPoint() {
        List<CustomizeMonitorBigScreenPointDto> bigScreenPoints = customizeMonitoringPointMapper.findBigScreenPointData(Context.getCompanyCode(), Context.getCurrentTenantId());
        MonitorPointDataWebSocket.sendInfo(bigScreenPoints, WebsocketDataType.CUSTOMIZE_MONITOR.getIndex());
    }

    @Override
    public void batchSwitch(MhMonitoringPointReqBean bean) {
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(bean.getIds())) {
            customizeMonitoringPointMapper.updateByIds(bean.getState(),bean.getIds());
        }
    }

    @Override
    public List<CustomizeMonitorLocationInfoDto> getLocationInfo() {
        List<CustomizeMonitorLocationInfoDto> all = customizeMonitoringPointMapper.allList(Context.getCompanyCode(), Context.getCurrentTenantId());
        all.forEach(each -> {
            String imageUrl = baseImageRepositoryService.generateImageUrlById(each.getImageId());
            each.setDownloadUrl(imageUrl);
        });
        return all;
    }

    @Override
    public CustomizeMonitorType getPointTypeInfoById(Long pointId) {
        CustomizeMonitorPoint point = super.getById(pointId);
        return customizeMonitorTypeService.getById(point.getCustomizeMonitoringTypeId());
    }

    @Override
    public Object monitorPointDetail(Long pointId) throws ApiBusinessException {
        CustomizeMonitorPoint point = super.getById(pointId);
        if (point != null) {
            CustomizeMonitorType customizeMonitorType = customizeMonitorTypeService.getById(point.getCustomizeMonitoringTypeId());
            if (customizeMonitorType != null) {
                String resultUrl = point.getBaseUrl();
                if (StringUtils.isBlank(point.getBaseUrl())) {
                    resultUrl = customizeMonitorType.getCustomizeUrl() + "?code=" + point.getPointCode();
                }
                return getMonitorPointDetailRespByHttp(resultUrl);
            } else {
                throw new ApiBusinessException(Status.MONITOR_POINT_TYPE_NOT_FIND_ERROR);
            }
        } else {
            throw new ApiBusinessException(Status.MONITOR_POINT_NOT_FIND_ERROR);
        }
    }


    private Object getMonitorPointDetailRespByHttp(final String httpUrl) throws ApiBusinessException {
        String response;
        log.info(">>>>>>>> Get monitor point detail httpUrl: " + httpUrl);
        long start = System.currentTimeMillis();
        response = HttpRequest.get(httpUrl).execute().body();
        long end = System.currentTimeMillis();
        long time = end - start;
        log.info(">>>>>>>> monitor point detail request" + " -> " + " cost " + time + "ms");
        log.info(">>>>>>>> monitor point detail response: " + response);
        CustomizeMonitorResult result = GsonUtils.fromJson(response, CustomizeMonitorResult.class);
        if (Status.SUCCESS.getCode() == result.getCode()) {
            return result.getData();
        } else {
            throw new ApiBusinessException(Status.GET_MONITOR_POINT_DETAIL_ERROR);
        }
    }
}
